package com.xjx.programmer.service;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.xjx.programmer.model.DatabaseConnection;
import com.xjx.programmer.model.ExecuteResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * MongoDB 数据库服务
 */
@Slf4j
@Service
public class MongoDbService {

    /**
     * 创建 MongoDB 客户端
     */
    public MongoClient createMongoClient(DatabaseConnection connection) {
        String connectionString = buildConnectionString(connection);
        return MongoClients.create(connectionString);
    }

    /**
     * 构建连接字符串
     */
    private String buildConnectionString(DatabaseConnection connection) {
        StringBuilder sb = new StringBuilder("mongodb://");
        
        if (connection.getUsername() != null && !connection.getUsername().isEmpty()) {
            sb.append(connection.getUsername());
            if (connection.getPassword() != null && !connection.getPassword().isEmpty()) {
                sb.append(":").append(connection.getPassword());
            }
            sb.append("@");
        }
        
        sb.append(connection.getHost()).append(":").append(connection.getPort());
        
        if (connection.getDatabaseName() != null && !connection.getDatabaseName().isEmpty()) {
            sb.append("/").append(connection.getDatabaseName());
        }
        
        return sb.toString();
    }

    /**
     * 执行 MongoDB 命令
     */
    public ExecuteResult executeCommand(DatabaseConnection connection, String command) {
        long startTime = System.currentTimeMillis();
        
        try (MongoClient mongoClient = createMongoClient(connection)) {
            MongoDatabase database = mongoClient.getDatabase(connection.getDatabaseName());
            
            // 解析命令
            Document commandDoc = Document.parse(command);
            Document result = database.runCommand(commandDoc);
            
            List<Map<String, Object>> data = new ArrayList<>();
            data.add(result);
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("命令执行成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .data(data)
                    .build();
                    
        } catch (Exception e) {
            log.error("执行 MongoDB 命令失败: {}", command, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("命令执行失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 查询集合数据
     */
    public ExecuteResult findDocuments(DatabaseConnection connection, String collectionName, String filter) {
        long startTime = System.currentTimeMillis();
        
        try (MongoClient mongoClient = createMongoClient(connection)) {
            MongoDatabase database = mongoClient.getDatabase(connection.getDatabaseName());
            MongoCollection<Document> collection = database.getCollection(collectionName);
            
            List<Map<String, Object>> data = new ArrayList<>();
            
            if (filter == null || filter.trim().isEmpty()) {
                // 查询所有文档
                for (Document doc : collection.find()) {
                    data.add(doc);
                }
            } else {
                // 根据过滤条件查询
                Document filterDoc = Document.parse(filter);
                for (Document doc : collection.find(filterDoc)) {
                    data.add(doc);
                }
            }
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("查询成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .data(data)
                    .build();
                    
        } catch (Exception e) {
            log.error("查询 MongoDB 文档失败: collection={}, filter={}", collectionName, filter, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("查询失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 插入文档
     */
    public ExecuteResult insertDocument(DatabaseConnection connection, String collectionName, String document) {
        long startTime = System.currentTimeMillis();
        
        try (MongoClient mongoClient = createMongoClient(connection)) {
            MongoDatabase database = mongoClient.getDatabase(connection.getDatabaseName());
            MongoCollection<Document> collection = database.getCollection(collectionName);
            
            Document doc = Document.parse(document);
            collection.insertOne(doc);
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("插入成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .affectedRows(1)
                    .build();
                    
        } catch (Exception e) {
            log.error("插入 MongoDB 文档失败: collection={}, document={}", collectionName, document, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("插入失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 测试数据库连接
     */
    public boolean testConnection(DatabaseConnection connection) {
        try (MongoClient mongoClient = createMongoClient(connection)) {
            MongoDatabase database = mongoClient.getDatabase(connection.getDatabaseName());
            database.runCommand(new Document("ping", 1));
            return true;
        } catch (Exception e) {
            log.error("测试 MongoDB 连接失败", e);
            return false;
        }
    }
}
